#include "common_includes.h"
#include "ftp_users_configuration_reader.h"
#include "access_control_entry.h"

#include <string>
#include <map>
#include <vector>

#ifndef ACCESSCONTROLMATRIX_H
#define ACCESSCONTROLMATRIX_H

AUTH_NS_START

// File is in following form:
// Header - |File Name |User/Grp Spc|User Id or Group ID     |Read        | Write      | Execute     | Positive or Negative|
// 			<FILE_NAME>:[USER|GROUP]:[<User_UID>|<Group_Gid>]:[ALLOW|DENY]:[ALLOW|DENY]:[ALLOW|DENY]:[+|-]
//			<FILE_NAME>:[USER|GROUP]:[<User_UID>|<Group_Gid>]:[ALLOW|DENY]:[ALLOW|DENY]:[ALLOW|DENY]:[+|-]


class AccessControlMatrix {

private:
	static AccessControlMatrix* ms_instance;

	/**
	 * @brief No Implementation to prevent Copy Ctor
	 * @param rhs
	 */
	AccessControlMatrix(const AccessControlMatrix& rhs);

	/**
	 * @brief No implementation to prevent shallow copy
	 * @param rhs
	 */
	AccessControlMatrix& operator=(const AccessControlMatrix& rhs);

	/**
	 * @brief Instantiates a Access Control Matrix. Private to make singleton
	 */
	AccessControlMatrix();

	FtpUsersConfigurationReader* m_nUserConfiguration;

	void Tokenize(const std::string& data, std::vector<std::string>& tokens);

protected:
	typedef std::multimap<std::string, AccessControlEntry*> AccessControlEntryListType;
	typedef std::pair<std::string, AccessControlEntry*> AccessControlEntryItem;
	typedef AccessControlEntryListType::const_iterator AccessControlEntryIterator;

	AccessControlEntryListType m_nAccessControlEntryList;

	virtual void ParseConfigFile(std::string configFilename);
public:
	/**
	 * @brief Returns the singleton instance
	 * @return the instance of FtpUserConfigurationReader
	 */
	static AccessControlMatrix* Instance();

	/**
	 * @brief Release the instance.
	 */
	static void Release();

	virtual ~AccessControlMatrix();

	/**
	 * @brief Initialize the ACM form the config File.
	 * @param configFilename The configuration File containing the rules.
	 */
	void Initialize(std::string configFilename);

	/**
	 * @brief Should the DesiredAccess be granted to the specified File
	 * @param filename The Target File
	 * @param desiredAccess The level of access desired
	 * @param user The User requesting access
	 * @return true if allowed, false otherwise.
	 */
	bool ShouldAllowAccess(std::string filename, AccessRightFlags desiredAccess, const FtpUser& user);

	/**
	 * @brief Gets the User Configuration Instance
	 * @return The User Configuration instance.
	 */
	const FtpUsersConfigurationReader* GetUserConfiguration() const {
		return m_nUserConfiguration;
	}
	
};

AUTH_NS_END

#endif // ACCESSCONTROLMATRIX_H
